package com.mes.cloud.util;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.math.BigDecimal;
import java.net.URLEncoder;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * 文件上传
 * Created by pactera on 2017-08-10.
 */
public class FileUtils {

    /**
     * 校验文件格式
      * @param filepath
     * @return
     * @throws Exception
     */
    public static String validFilePath(String filepath) throws Exception {
        List<String> allowedExtensions = new ArrayList<String>();
        boolean result = false;
        allowedExtensions.add(".jpg");
        allowedExtensions.add(".png");
        allowedExtensions.add(".bmp");
        allowedExtensions.add(".gif");

        allowedExtensions.add(".wps");
        allowedExtensions.add(".doc");
        allowedExtensions.add(".docx");
        allowedExtensions.add(".xls");
        allowedExtensions.add(".xlsx");
        allowedExtensions.add(".pdf");
        allowedExtensions.add(".ppt");
        allowedExtensions.add(".pptx");
        for (String suf : allowedExtensions) {
            if (filepath.endsWith(suf)) {
                result = true;
                break;
            }
        }
        if (!result) {
            // 按指定模式在字符串查找
            String pattern1 = "(.*)(\\.log\\.{0,1}\\d{0,})$";
            // 创建 Pattern 对象
            Pattern r1 = Pattern.compile(pattern1);
            // 现在创建 matcher 对象
            Matcher m1 = r1.matcher(filepath);
            if (!m1.matches()) {
                Exception Exception = new Exception("file name is Illage");
                throw Exception;
            }
        }
        filepath.replaceAll("../", "");
        filepath.replaceAll("..\\\\", "");
        return filepath;
    }

    /**
     * 检查文件大小
     *
     * @param file_size
     * @param size
     * @return
     */
    public static boolean checkSize(double file_size, double size) {
        if (file_size > size) {// 判断文件大小是否超出限制范围
            return true;
        } else {
            return false;
        }
    }


    /***
     * @methodName encodeFilename
     * @date 2018/5/21 14:38
     * @param filename, request
     * @return java.lang.String
     * 设置下载文件中文件的名字
     */

    public static String encodeFilename(String filename, HttpServletRequest request){
        //获得浏览器信息并转换为大写
        String userAgent = request.getHeader("User-Agent").toUpperCase();
        try {
            if(userAgent.contains("MSIE")){//IE浏览器
                filename = URLEncoder.encode(filename,"UTF-8");
            }else if(userAgent.contains("Mozilla")){//google,火狐浏览器
                filename = new String(filename.getBytes("UTF-8"), "ISO8859-1");
            }else{
                filename = URLEncoder.encode(filename,"UTF-8");//其他浏览器
            }
            return filename;
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
            return filename;
        }
    }

    /***
     * @methodName encodeFilename
     * @date 2018/5/21 14:38
     * @param filename, request
     * @return java.lang.String
     * 设置下载文件中文件的名字
     */

    public static String encodeFilename(String filename, String userAgent){
        //获得浏览器信息并转换为大写
        userAgent = userAgent.toUpperCase();
        try {
            if(userAgent.contains("MSIE")){//IE浏览器
                filename = URLEncoder.encode(filename,"UTF-8");
            }else if(userAgent.contains("Firefox")){//火狐浏览器
                filename = new String(filename.getBytes("UTF-8"), "ISO8859-1");
            }else if(userAgent.contains("Chrome")){ //谷歌浏览器
                filename = URLEncoder.encode(filename,"UTF-8");
            }else {//其他浏览器
                filename = URLEncoder.encode(filename,"UTF-8");
            }
            return filename;
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
            return filename;
        }
    }



    /**
     * @param request
     * @param response
     * @param length 文件绝对路径(包括文件名和扩展名)
     * @param showName 下载后看到的文件名
     * @return 文件名
     */
    public static void downloadFile(HttpServletRequest request, HttpServletResponse response, InputStream input, long length, String showName)throws Exception {
        String info = request.getHeader("User-Agent").toLowerCase();
        if (info.contains("firefox")) { // Firefox
            showName = new String(showName.getBytes(), "ISO-8859-1");
        } else { // IE,Chrome
            showName = URLEncoder.encode(showName, "UTF-8");
        }
        response.reset(); // 响应重置
        response.setHeader("Content-Disposition", "attachment; filename=\""+ showName + "\"");
        response.addHeader("Content-Length", ""+length);
        response.setContentType("application/octet-stream;charset=UTF-8");
        OutputStream out = response.getOutputStream();
        int len = 0;
        byte[] buffer = new byte[1024*8];
        while ((len = input.read(buffer)) != -1) {
            out.write(buffer,0,len);
        }
        input.close();
        response.flushBuffer();
    }
    public static void downloadFile(HttpServletRequest request, HttpServletResponse response, File file, String showName) throws Exception {
        downloadFile(request, response, new FileInputStream(file), file.length(), showName);
    }
    public static void downloadFile(HttpServletRequest request, HttpServletResponse response, String fileAbsPath, String showName) throws Exception{
        downloadFile(request, response, new File(fileAbsPath), showName);
    }

    //返回文件大小：以B、KB、MB等展示
    public static String getPrintSize(long size) {
        // 如果字节数少于1024，则直接以B为单位，否则先除于1024，后3位因太少无意义
        double value = (double) size;
        if (value < 1024) {
            return String.valueOf(value) + "B";
        } else {
            value = new BigDecimal(value / 1024).setScale(2, BigDecimal.ROUND_DOWN).doubleValue();
        }
        // 如果原字节数除于1024之后，少于1024，则可以直接以KB作为单位
        // 因为还没有到达要使用另一个单位的时候
        // 接下去以此类推
        if (value < 1024) {
            return String.valueOf(value) + "KB";
        } else {
            value = new BigDecimal(value / 1024).setScale(2, BigDecimal.ROUND_DOWN).doubleValue();
        }
        if (value < 1024) {
            return String.valueOf(value) + "MB";
        } else {
            // 否则如果要以GB为单位的，先除于1024再作同样的处理
            value = new BigDecimal(value / 1024).setScale(2, BigDecimal.ROUND_DOWN).doubleValue();
            return String.valueOf(value) + "GB";
        }
    }

    //获取文件类型
    public static String getFileType(File file) {
        String res = null;
        FileInputStream fis = null;
        try {
            fis = new FileInputStream(file);
            //获取文件头的前六位
            byte[] b = new byte[3];
            fis.read(b, 0, b.length);
            String fileCode = bytesToHexString(b);
            Iterator<String> keyIter = FILE_TYPE_MAP.keySet().iterator();
            while (keyIter.hasNext()) {
                String key = keyIter.next();
                //比较前几位是否相同就可以判断文件格式（相同格式文件文件头后面几位会有所变化）
                if (key.toLowerCase().startsWith(fileCode.toLowerCase()) || fileCode.toLowerCase().startsWith(key.toLowerCase())) {
                    res = FILE_TYPE_MAP.get(key);
                    break;
                }
            }
            fis.close();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (fis != null) {
                    fis.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return res;
    }

    /**
     * 得到上传文件的文件头
     *
     * @param src
     * @return
     */
    private static String bytesToHexString(byte[] src) {
        StringBuilder stringBuilder = new StringBuilder();
        if (null == src || src.length <= 0) {
            return null;
        }
        for (int i = 0; i < src.length; i++) {
            int v = src[i] & 0xFF;
            String hv = Integer.toHexString(v);
            if (hv.length() < 2) {
                stringBuilder.append(0);
            }
            stringBuilder.append(hv);
        }
        return stringBuilder.toString();
    }
    private final static Map<String, String> FILE_TYPE_MAP = new HashMap<String, String>();
    static {
        getAllFileType();  //初始化文件类型信息
    }
    private static void getAllFileType() {
        FILE_TYPE_MAP.put("ffd8ffe000104a464946", "jpg"); //JPEG (jpg)
        FILE_TYPE_MAP.put("89504e470d0a1a0a0000", "png"); //PNG (png)
        FILE_TYPE_MAP.put("47494638396126026f01", "gif"); //GIF (gif)
        FILE_TYPE_MAP.put("424d228c010000000000", "bmp"); //16色位图(bmp)
        FILE_TYPE_MAP.put("424d8240090000000000", "bmp"); //24位位图(bmp)
        FILE_TYPE_MAP.put("424d8e1b030000000000", "bmp"); //256色位图(bmp)
        FILE_TYPE_MAP.put("d0cf11e0a1b11ae10000", "doc"); //MS Excel 注意：word、msi 和 excel的文件头一样
        FILE_TYPE_MAP.put("255044462d312e360d25", "pdf"); //Adobe Acrobat (pdf)
        FILE_TYPE_MAP.put("504b0304140006000800", "docx");//docx文件
        FILE_TYPE_MAP.put("d0cf11e0a1b11ae10000", "wps");//WPS文字wps、表格et、演示dps都是一样的
    }
}
